package com.changgou.seckill.task;

import com.alibaba.fastjson.JSON;
import com.changgou.seckill.dao.SeckillGoodsMapper;
import com.changgou.seckill.dao.SeckillOrderMapper;
import com.changgou.seckill.pojo.SeckillGoods;
import com.changgou.seckill.pojo.SeckillOrder;
import entity.IdWorker;
import entity.SeckillStatus;
import org.springframework.amqp.AmqpException;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.core.MessagePostProcessor;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Component;

import java.util.Date;

@Component
public class MultiThreadingCreateOrder {


    @Autowired
    private SeckillOrderMapper seckillOrderMapper;

    @Autowired
    private SeckillGoodsMapper seckillGoodsMapper;

    @Autowired
    private IdWorker idWorker;
    @Autowired
    private RedisTemplate redisTemplate;

    @Autowired
    private RabbitTemplate rabbitTemplate;
    /***
     * 多线程下单操作
     */
    @Async
    public void createOrder(){
        try {

            /***
             * 下单实现
             * @param id:商品ID
             * @param time:商品秒杀开始时间
             * @param username:用户登录名
             * @return
             */

            //从redis中取出数据，进行下单
            SeckillStatus seckillStatus = (SeckillStatus) redisTemplate.boundListOps("SeckillOrderQueue").rightPop();
            if (seckillStatus ==null){
                return;
            }
            //先到SeckillGoodsCountList_id队列中获取该商品的一个信息，如果能获取则直接下单
            Object sgoods = redisTemplate.boundListOps("SeckillGoodsCountList_" + seckillStatus.getGoodsId()).rightPop();
            //如果不能获取该商品的队列信息，则表示没有库存，清理排队信息，可以再次进行抢购
            if (sgoods ==null){
                clearUserQueue(seckillStatus.getUsername());
                return;
            }


            String username = seckillStatus.getUsername();
            String time = seckillStatus.getTime();
            Long id = seckillStatus.getGoodsId();
            //查询秒杀商品
            String namespace = "SeckillGoods_"+time;
            SeckillGoods seckillGoods = (SeckillGoods) redisTemplate.boundHashOps(namespace).get(id);
            //判断有木有库存
            Integer stockCount = seckillGoods.getStockCount();
            if (stockCount<=0 || stockCount==null){
                throw new RuntimeException("已经停售");
            }
            //创建订单对象
            SeckillOrder seckillOrder = new SeckillOrder();
            seckillOrder.setId(idWorker.nextId());
            seckillOrder.setSeckillId(id); //商品id
            seckillOrder.setMoney(seckillGoods.getCostPrice());//支付金额
            seckillOrder.setUserId(username); //用户名
            seckillOrder.setCreateTime(new Date());  //下单时间
            seckillOrder.setStatus("0"); //支付状态 未支付
            //将订单存起来
            /**
             * 将订单对象储存起来
             * 1，一个用户只允许一个未支付秒杀订单
             * 2，订单存入redis
             *      Hash
             *         namespace-》seckillOrder
             *                     username：seckillOrder
             */

            redisTemplate.boundHashOps("seckillOrder").put(username,seckillOrder);

            /***
             * 库存递减
             *   redis.StockCount
             *   商品可能是最后一个，如果是最后一个，则将redis中的商品删除，并且将redis中该商品的数据同步到mysql
             *
             */
            //每次库存减一
            seckillGoods.setStockCount(seckillGoods.getStockCount()-1);
            //获取商品对应队列中的数据
            Long size = redisTemplate.boundListOps("SeckillGoodsCountList_" + seckillStatus.getOrderId()).size();

            /*if (seckillGoods.getStockCount()<=0)*/
            if (size<=0){
                //同步到mysql
                seckillGoodsMapper.updateByPrimaryKeySelective(seckillGoods);
                //删除redis中的商品数据
                redisTemplate.boundHashOps(namespace).delete(id);
            }else {
                //同步数据到redis
                redisTemplate.boundHashOps(namespace).put(id,seckillGoods);
            }
            //下单成功 更新订单状态  seckillStatus
            seckillStatus.setOrderId(seckillOrder.getId());   //id
            seckillStatus.setMoney(Float.valueOf(seckillGoods.getCostPrice()));//支付金额
            seckillStatus.setStatus(2); //待付款

            //发送消息给延时队列
            rabbitTemplate.convertAndSend("delayMessageQueue", (Object) JSON.toJSONString(seckillStatus), new MessagePostProcessor() {
                @Override
                public Message postProcessMessage(Message message) throws AmqpException {
                    message.getMessageProperties().setExpiration("1000");
                    return message;
                }
            });

            redisTemplate.boundHashOps("UserQueueStatus").put(username,seckillStatus);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /***
     * 清空排队信息
     * @param username
     */
    public void clearUserQueue(String username){
        //排队标识
        redisTemplate.boundHashOps("UserQueueCount").delete(username);
        //排队信息清理
        redisTemplate.boundHashOps("UserQueueStatus").delete(username);
    }
}
